package com.bluemoon.bmwalk.common.jacoco;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.bluemoon.bmwalk.common.jacoco.dto.Clazz;
import com.bluemoon.bmwalk.common.jacoco.dto.Counter;
import com.bluemoon.bmwalk.common.jacoco.dto.Method;
import com.bluemoon.bmwalk.common.jacoco.dto.Package;
import com.bluemoon.bmwalk.common.jacoco.dto.Report;

import lombok.extern.slf4j.Slf4j;

/**
 * 解析jacoco覆盖率报告工具类
 * @author: liaozhioyng
 * @create: 2024-01-03
 */
@Slf4j
public class ParseJacocoXmlUtil {
    /**
     * 解析jacoco覆盖率报告
     *
     * @param xmlPath jacoco覆盖率报告路径
     * @return 解析后的报告对象，解析失败时返回null
     */
    public static Report parse(String xmlPath) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // 禁用DTD验证
            factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            SAXParser saxParser = factory.newSAXParser();
            // 读取xml文件
            File xmlFile = new File(xmlPath);
            ParseXmlHandler handler = new ParseXmlHandler();
            try (InputStream inputStream = xmlFile.toURI().toURL().openStream()) {
                // 解析XML文件
                saxParser.parse(inputStream, handler);
                return handler.getReport();
            }
        } catch (ParserConfigurationException | SAXException | IOException e) {
            log.error("解析jacoco xml 覆盖率报告失败", e);
        }
        return null;
    }

    public static void main(String[] args) {
        // 指定XML文件路径
        String xmlFilePath = "D:\\workblue\\jacoco_bmwalk\\src\\main"
        		+ "\\java\\com\\bluemoon\\bmwalk\\common\\jacoco\\dto\\report.xml";
        //String xmlFilePath = "F:\\temp\\a.xml";
        Report report = ParseJacocoXmlUtil.parse(xmlFilePath);
        Optional.ofNullable(report).ifPresent(ParseJacocoXmlUtil::export);
    }

    public static void export(Report report) {
        for (Package pkg : report.getPackages()) {
            System.out.println("Package Name: " + pkg.getName());

            for (Clazz clazz : pkg.getClasses()) {
                System.out.println("Class Name: " + clazz.getName());

                for (Method method : clazz.getMethods()) {
                    System.out.println("Method Name: " + method.getName());
                    System.out.println("Method Description: " + method.getDesc());

                    for (Counter counter : method.getMethodCounters()) {
                        System.out.println("Counter Type: " + counter.getType());
                        System.out.println("Counter Missed: " + counter.getMissed());
                        System.out.println("Counter Covered: " + counter.getCovered() + "\n");
                    }
                    System.out.println("==================== Method ==========================================");
                }
            }
        }
    }
    
}
